package com.gopay.common.util;

import org.apache.commons.lang3.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串脱敏工具类
 * 用正则表达式处理k=v或k=[v]形式的敏感信息value，保留前后各1-4位，其余*号
 * 例如：certNo=5303****987X&mobile=156****6821&cardNo=9558****3542 或 VerficationCode=[11****aa]
 * Created by fanghw on 2017/3/21.
 */
public class StringMaskUtil {
    /**
     * 脱敏显示字符
     */
    private static final String MASK_CHAR="****";

    /**
     * 身份证，卡号，手机号 正则表达式
     */
    private static Pattern CERT_CARD_MOBILE_PATTERN = Pattern.compile("^[0-9]{7,24}[xX]?$");

    /**
     * 对单个key脱敏
     * @param text
     * @param key
     * @return
     */
    public static String mask(String text, String key) {
        return mask(text,new String[]{key});
    }

    /**
     * 对key数组脱敏
     * @param text
     * @param keys
     * @return
     */
    public static String mask(String text, String[] keys) {
        try {
            String patternStr = "(" + StringUtils.join(keys, "|") + ")\\=(\\[)?([a-zA-Z0-9\\-]+)(\\])?";
            Pattern pattern = Pattern.compile(patternStr);
            Matcher matcher = pattern.matcher(text);

            StringBuffer sb = new StringBuffer();
            while (matcher.find()) {
                int count = matcher.groupCount();
                String value = count > 2 ? matcher.group(3) : matcher.group(2);

                String dark = MASK_CHAR;
                if (value.length() >2) {
                    int restHeadCount=value.length() > 4?2:1;
                    int restTailCount=restHeadCount;
                    if(CERT_CARD_MOBILE_PATTERN.matcher(value).matches()){
                       if(value.startsWith("1")&&value.length()==11){
                           //手机号
                           restHeadCount=3;
                           restTailCount=4;
                       }else{
                           //证件号，卡号
                           restHeadCount=4;
                           restTailCount=4;
                       }
                    }
                    dark = value.substring(0, restHeadCount) + MASK_CHAR + value.substring(value.length() - restTailCount);
                }

                String res = matcher.group(0).replace(value, dark);

                matcher.appendReplacement(sb, res);
            }
            matcher.appendTail(sb);

            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return text;
    }
    public static void main(String[] args) {
        String s1="appId=10021&userId=000321&mobile=15628946821,15201914485&code=927803&time=20170321103841&secretKey=09abc48-5ef6-4e76-b93c-f68xvm0985ef1";
        System.out.println(s1);
        System.out.println(mask(s1,new String[]{"code","secretKey","mobile"}));

        s1="version=[2.2]tranCode=[8888]merchantID=[0000043740]tranDateTime=[20170321112340]VerficationCode=[11111aaaaa]";
        System.out.println(s1);
        System.out.println(mask(s1,"VerficationCode"));

        s1="certNo=53032219901223987X&mobile=15628946821&cardNo=9558800200159873542&time=20170321103841";
        System.out.println(s1);
        System.out.println(mask(s1,new String[]{"certNo","mobile","cardNo"}));

    }

}
